package com.test.netty.demo.util;

import io.netty.buffer.ByteBuf;
import io.netty.handler.codec.http.FullHttpRequest;
import io.netty.handler.codec.http.QueryStringDecoder;
import io.netty.handler.codec.http.multipart.Attribute;
import io.netty.handler.codec.http.multipart.HttpPostRequestDecoder;
import io.netty.handler.codec.http.multipart.InterfaceHttpData.HttpDataType;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.*;

import org.json.XML;
import org.springframework.util.StringUtils;

import com.alibaba.fastjson.JSONException;
import com.alibaba.fastjson.JSONObject;

/**
 * 参数解析
 *
 * @author yousj
 */
public class ParamsAnalyze {

    public Map<String, Object> analyzeGetParams(QueryStringDecoder decoder, FullHttpRequest request) {
        Map<String, Object> requestData = new HashMap<>();
        //个性字段处理
        Map<String, List<String>> rm = decoder.parameters();
        rm.keySet().forEach(s -> {
            if (rm.get(s) != null) requestData.put(s, rm.get(s).get(0));
        });
        requestData.put("path", decoder.path());
        String[] service = decoder.path().split("/");
        //接口地址处理规则 /pro/path/method
        requestData.put("service", service[service.length - (service.length > 3 ? 2 : 1)]);
        requestData.put("method", service.length > 3 ? service[service.length - 1] : "execute");
        requestData.put("headers", this.analyzeHeaders(request));
        return requestData;
    }

    public Map<String, Object> analyzePostParams(HttpPostRequestDecoder decoder, FullHttpRequest request) {
        Map<String, Object> requestData = analyzeGetParams(new QueryStringDecoder(request.getUri()), request);
        String strContentType = request.headers().get("Content-Type").trim();
        if (strContentType.contains("x-www-form-urlencoded")) {
            decoder.offer(request);
            decoder.getBodyHttpDatas().forEach(iData -> {
                if (iData.getHttpDataType() == HttpDataType.Attribute) {
                    Attribute attribute = (Attribute) iData;
                    try {
                        requestData.put(iData.getName(), attribute.getValue());
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            });
        } else if (strContentType.contains("application/json")) {
            ByteBuf content = request.content();
            byte[] reqContent = new byte[content.readableBytes()];
            content.readBytes(reqContent);
            String strContent = "";
            try {
                strContent = new String(reqContent, StandardCharsets.UTF_8);
                if (!StringUtils.isEmpty(strContent)) {
                    JSONObject jo = JSONObject.parseObject(strContent);
                    jo.keySet().forEach(key -> requestData.put(key, jo.get(key)));
                }
                requestData.put("jsonVerify", true);
            } catch (JSONException e) {
                //对于部分xml的json用xml方式解析一次
                formatXML(strContent, requestData);
                requestData.put("xmlVerify", true);
            } catch (Exception e) {
                requestData.put("jsonVerify", false);
                e.printStackTrace();
            }
        } else if (strContentType.contains("xml")) {
            ByteBuf content = request.content();
            byte[] reqContent = new byte[content.readableBytes()];
            content.readBytes(reqContent);
            String strContent;
            try {
                strContent = new String(reqContent, StandardCharsets.UTF_8);
                if (!StringUtils.isEmpty(strContent)) formatXML(strContent, requestData);
                requestData.put("xmlVerify", true);
            } catch (Exception e) {
                requestData.put("xmlVerify", false);
                e.printStackTrace();
            }
        }
        return requestData;
    }

    private static void formatXML(String strContent, Map<String, Object> requestData) {
        org.json.JSONObject xmlJSONObj = XML.toJSONObject(strContent);
        for (String key1 : xmlJSONObj.keySet()) {
            if (xmlJSONObj.get(key1) instanceof org.json.JSONObject) {
                org.json.JSONObject xo = (org.json.JSONObject) xmlJSONObj.get(key1);
                xo.keySet().forEach(key2 -> requestData.put(key2, xo.get(key2)));
            }
        }
    }


    /**
     * header处理
     *
     * @param request
     * @return
     */
    private Map<String, String> analyzeHeaders(FullHttpRequest request) {
        Map<String, String> headerData = null;
        Set<String> names = request.headers().names();
        if (names != null) {
            headerData = new HashMap<>();
            for (String name : names) {
                headerData.put(name, request.headers().get(name));
            }
        }
        return headerData;
    }

    public static Map<String, Object> analyzeUriParams(String uri) {
        if (uri.startsWith("/")) uri = uri.substring(uri.indexOf("/") + 1);
        if (uri.startsWith("?")) uri = uri.substring(uri.indexOf("?") + 1);
        Map<String, Object> r = new HashMap<>();
        StringTokenizer st = new StringTokenizer(uri, "&");
        while (st.hasMoreTokens()) {
            StringTokenizer stv = new StringTokenizer(st.nextToken(), "=");
            while (stv.hasMoreTokens()) {
                r.put(stv.nextToken(), stv.hasMoreTokens() ? stv.nextToken() : "");
            }
        }
        return r;
    }

}
